﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace Skugo.Shared
{
    /// <summary>
    /// A packet type denotes the intentions of the packet.
    /// </summary>
    public enum PacketType : byte
    {
        /// <summary>
        /// Marks that a packet type is not valid (this should never be encountered).
        /// </summary>
        Invalid,

        /// <summary>
        /// Initializes the remote client with the project settings (name, etc).
        /// </summary>
        Initialize,

        /// <summary>
        /// The packet's intention is to create a remote plugin.
        /// </summary>
        Create,

        /// <summary>
        /// The packet's intention is to destroy a remote plugin.
        /// </summary>
        Destroy,

        /// <summary>
        /// The packet is simply a communication between plugins.
        /// </summary>
        Message,

        /// <summary>
        /// A value was dragged between one plugin to another.
        /// It will be recieved on the plugin it gets dropped on,
        /// however, the source plugin will be responsible for
        /// deserializing the drag drop data into an object on
        /// the remote side.
        /// </summary>
        DragDrop,
    }

    public static class Packet
    {
        public delegate void PacketWriteFn(BinaryWriter outgoing);

        public static Byte[] Make(PacketWriteFn create)
        {
            // Create a memory stream to write data to
            MemoryStream stream = new MemoryStream();

            // Create a binary writer to write the data
            BinaryWriter outgoing = new BinaryWriter(stream);

            // Now write the rest of the packet
            create(outgoing);

            // Return the data to be sent
            return stream.ToArray();
        }
    }

    /// <summary>
    /// A packet header consists of all the information that gets sent in the packet.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct PacketHeader
    {
        /// <summary>
        /// An invalid data size constant.
        /// </summary>
        public const UInt32 InvalidDataSize = 0xFFFFFFFF;

        /// <summary>
        /// The size of the header.
        /// </summary>
        public const UInt32 Size = sizeof(UInt32) + sizeof(PacketType) + sizeof(Int64);

        /// <summary>
        /// The size of the data in the packet (not incling header size).
        /// </summary>
        public UInt32 DataSize;

        /// <summary>
        /// Store the type of the packet (basically, what are our intentions).
        /// </summary>
        public PacketType Type;

        /// <summary>
        /// The unique ID of the plugin (so that we know who its intended for).
        /// </summary>
        public Int64 InstanceGuid;
    };
}
